/**
 * Project: dubbo.registry-1.1.0-SNAPSHOT
 * 
 * File Created at 2010-4-15
 * $Id: Route.java 184666 2012-07-05 11:13:17Z tony.chenl $
 * 
 * Copyright 2008 Alibaba.com Croporation Limited.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * Alibaba Company. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Alibaba.com.
 */
package com.alibaba.dubbo.registry.common.domain;

import java.util.List;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;

/**
 * Route
 * 
 * @author william.liangf
 */
public class Route extends Entity {

	private static final long serialVersionUID = -7630589008164140656L;

	public static final String ALL_METHOD = "*";

	/**
	 * 路由规则是否在消费者运行期间内也动态下发
	 */
	public static final boolean RUNTIME = true;

	// WHEN KEY

	public static final String KEY_METHOD = "method";

	public static final String KEY_CONSUMER_APPLICATION = "consumer.application";

	public static final String KEY_CONSUMER_GROUP = "consumer.cluster";

	public static final String KEY_CONSUMER_VERSION = "consumer.version";

	public static final String KEY_CONSUMER_HOST = "consumer.host";

	public static final String KEY_CONSUMER_METHODS = "consumer.methods";

	// THEN KEY

	public static final String KEY_PROVIDER_APPLICATION = "provider.application";

	public static final String KEY_PROVIDER_GROUP = "provider.cluster";

	public static final String KEY_PROVIDER_PROTOCOL = "provider.protocol";

	public static final String KEY_PROVIDER_VERSION = "provider.version";

	public static final String KEY_PROVIDER_HOST = "provider.host";

	public static final String KEY_PROVIDER_PORT = "provider.port";

	private long parentId; // 默认为0

	private String name;

	private String service;

	private String rule;

	private String matchRule;

	private String filterRule;

	private int priority;

	private String username;

	private boolean enabled;

	private boolean force;

	private boolean isGlobal;
	
	/**
	 * 全局理由规则可以自动启用，如果设置为true，则全局规则创建好就会自动启用，如果自动启用为true时要禁用全局规则，只能选择删除，否则定时器会将其从禁用变成启用
	 */
	private boolean autoStartup;

	private List<Route> children;

	public Route() {
	}

	public Route(Long id) {
		super(id);
	}

	public int getPriority() {
		return priority;
	}

	public void setPriority(int priority) {
		this.priority = priority;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public long getParentId() {
		return parentId;
	}

	public void setParentId(long parentId) {
		this.parentId = parentId;
	}

	public List<Route> getChildren() {
		return children;
	}

	public void setChildren(List<Route> subRules) {
		this.children = subRules;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public boolean isEnabled() {
		return enabled;
	}

	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	public boolean isForce() {
		return force;
	}

	public void setForce(boolean force) {
		this.force = force;
	}

	public String getService() {
		return service;
	}

	public void setService(String service) {
		this.service = service;
	}

	public String getRule() {
		return rule;
	}

	public void setRule(String rule) {
		this.rule = rule;
		String[] rules = rule.split(" => ");
		if (rules.length != 2) {
			throw new IllegalArgumentException("Illegal Route Condition Rule");
		}
		this.matchRule = rules[0];
		this.filterRule = rules[1];
	}

	public String getMatchRule() {
		return matchRule;
	}

	public void setMatchRule(String matchRule) {
		this.matchRule = matchRule;
	}

	public String getFilterRule() {
		return filterRule;
	}

	public void setFilterRule(String filterRule) {
		this.filterRule = filterRule;
	}

	public boolean isGlobal() {
		return isGlobal;
	}

	public void setGlobal(boolean isGlobal) {
		this.isGlobal = isGlobal;
	}

	public boolean isAutoStartup() {
		return autoStartup;
	}

	public void setAutoStartup(boolean autoStartup) {
		this.autoStartup = autoStartup;
	}

	public URL toUrl() {
		String group = null;
		String version = null;
		String path = service;
		int i = path.indexOf("/");
		if (i > 0) {
			group = path.substring(0, i);
			path = path.substring(i + 1);
		}
		i = path.lastIndexOf(":");
		if (i > 0) {
			version = path.substring(i + 1);
			path = path.substring(0, i);
		}
		return URL.valueOf(Constants.ROUTE_PROTOCOL + "://" + Constants.ANYHOST_VALUE + "/" + path + "?" + Constants.CATEGORY_KEY + "="
				+ Constants.ROUTERS_CATEGORY + "&router=condition&runtime=" + RUNTIME + "&enabled=" + isEnabled() + "&isGlobal=" + isGlobal() + "&autoStartup="
				+ isAutoStartup() + "&priority=" + getPriority() + "&force=" + isForce() + "&dynamic=false" + "&name=" + getName() + "&" + Constants.RULE_KEY
				+ "=" + URL.encode(getMatchRule() + " => " + getFilterRule()) + (group == null ? "" : "&" + Constants.GROUP_KEY + "=" + group)
				+ (version == null ? "" : "&" + Constants.VERSION_KEY + "=" + version));
	}
	
	public GlobalRoute toGlobalRoute() {
		GlobalRoute globalRoute = new GlobalRoute();
		globalRoute.setAutoStartup(this.isAutoStartup());
		globalRoute.setChildren(this.getChildren());
		globalRoute.setCreated(this.getCreated());
		globalRoute.setEnabled(this.isEnabled());
		globalRoute.setFilterRule(this.getFilterRule());
		globalRoute.setForce(this.isForce());
		globalRoute.setGlobal(this.isGlobal());
		globalRoute.setId(this.getId());
		globalRoute.setIds(this.getIds());
		globalRoute.setMatchRule(this.getMatchRule());
		globalRoute.setMiss(this.isMiss());
		globalRoute.setModified(this.getModified());
		globalRoute.setName(this.getName());
		globalRoute.setNow(this.getNow());
		globalRoute.setOperator(this.getOperator());
		globalRoute.setOperatorAddress(this.getOperatorAddress());
		globalRoute.setParentId(this.getParentId());
		globalRoute.setPriority(this.getPriority());
		globalRoute.setRule(this.getRule());
		globalRoute.setService(this.getService());
		globalRoute.setUsername(this.getUsername());
		return globalRoute;
	}
	
	@java.lang.Override
	public String toString() {
		return "Route [parentId=" + parentId + ", name=" + name + ", service=" + service + ", rule=" + rule + ", matchRule=" + matchRule + ", filterRule="
				+ filterRule + ", priority=" + priority + ", username=" + username + ", enabled=" + enabled + ", force=" + force + ", isGlobal=" + isGlobal
				+ ", autoStartup=" + autoStartup + ", children=" + children + "]";
	}

	@java.lang.Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((filterRule == null) ? 0 : filterRule.hashCode());
		result = prime * result + ((matchRule == null) ? 0 : matchRule.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + ((rule == null) ? 0 : rule.hashCode());
		result = prime * result + ((service == null) ? 0 : service.hashCode());
		return result;
	}

	@java.lang.Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Route other = (Route) obj;
		if (filterRule == null) {
			if (other.filterRule != null)
				return false;
		} else if (!filterRule.equals(other.filterRule))
			return false;
		if (matchRule == null) {
			if (other.matchRule != null)
				return false;
		} else if (!matchRule.equals(other.matchRule))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (rule == null) {
			if (other.rule != null)
				return false;
		} else if (!rule.equals(other.rule))
			return false;
		if (service == null) {
			if (other.service != null)
				return false;
		} else if (!service.equals(other.service))
			return false;
		return true;
	}

}
